<template>
  <el-dialog
    :visible="showVisible"
    center
    :show-close="false"
    :append-to-body="true"
    width="680px"
  >
    <div class="b g3 f16 tl" slot="title">
      <div class="ks-row-between pl15 pr15">
        <span>{{ isNew ? "新建逻辑验证规则" : "编辑逻辑验证规则" }}</span>
        <span class="el-icon-close g9 f26 poi" @click="handleCancel"></span>
      </div>
    </div>

    <div class="pl30 pr30">
      <el-form :model="formData" ref="form" label-width="120px">
        <el-form-item
          label="类型"
          prop="type"
          :rules="[
            { required: true, message: '请选择类型', trigger: 'change' },
          ]"
        >
          <template slot="label">
            类型
            <el-tooltip popper-class="custom-popper" placement="top">
              <div slot="content">
                <div>唯一性校验</div>
                <div class="mt5">
                  实体业务模型数据新增、编辑时指定字段的联合唯一性校验。对于树结构业务模型，可以设置校验域，支持同层级、同层级及子节点、仅根级三种域。仅支持实体业务模型。
                </div>
                <div class="mt10">关联性规则校验</div>
                <div class="mt5">
                  用于配置实体业务模型的关联数据字典字段在删除时的校验规则，可以配置指定关联数据字段在等于或不等于特定的字典选项时，
                  无法删除数据。</div>
                <div class="mt10">引用性规则校验</div>
                <div class="mt5">
                  用于配置实体业务模型的唯一性字段（主要是ID）在删除时的校验规则，一般用于关联数据删除校验的场景，
                  如：B为供应商业务模型，A为产品业务模型，产品模型中字段A供应商为关联选择类型,关联了B业务模型，在删除B业务模型时，需要去校验B有没有被A关联选择，如果关联了则无法删除。
                </div>
              </div>
              <i class="el-icon-question" />
            </el-tooltip>
          </template>
          <el-select
            style="width: 100%"
            v-model="formData.type"
            placeholder=""
            @change="handleTypeChange"
          >
            <el-option
              v-for="(value, key) in typeList"
              :key="key"
              :value="key"
              :label="value"
            />
          </el-select>
        </el-form-item>
        <el-form-item
          v-show="formData.type === 'UNIQUE'"
          label="参与校验字段"
          prop="fieldCodes"
          :rules="[
            {
              required: formData.type === 'UNIQUE',
              message: '请选择参与校验字段',
              trigger: 'change',
            },
          ]"
        >
          <el-select
            v-model="formData.fieldCodes"
            multiple
            filterable
            style="width: 100%"
          >
            <el-option
              v-for="(item, index) in validateFieldList"
              :key="index"
              :value="item.code"
              :label="`${item.name}(${item.code})`"
            />
          </el-select>
        </el-form-item>

        <el-form-item
          v-show="formData.type === 'UNIQUE'"
          label="影响范围"
          prop="actionScope"
          :rules="[
            {
              required: formData.type === 'UNIQUE',
              message: '请选择影响范围',
              trigger: 'change',
            },
          ]"
        >
          <el-radio-group v-model="formData.actionScope">
            <el-radio
              v-for="(label, key) in scopeEnum"
              :label="key"
              :key="key"
              >{{ label }}</el-radio
            >
          </el-radio-group>
        </el-form-item>

        <el-form-item
          v-show="formData.type === 'REFERENCE'"
          label="被引用字段"
          prop="fieldCode"
          :rules="[
            {
              required: formData.type === 'REFERENCE',
              message: '请选择字段',
              trigger: 'change',
            },
          ]"
        >
          <el-select
            v-model="formData.fieldCode"
            filterable
            style="width: 100%"
          >
            <el-option
              v-for="(item, index) in referencedFieldList"
              :key="index"
              :value="item.code"
              :label="`${item.name}(${item.code})`"
            />
          </el-select>
        </el-form-item>

        <el-form-item
          v-if="formData.type === 'REFERENCE'"
          label="引用业务模型"
          prop="referenceModelCode"
          :rules="[
            {
              required: true,
              message: '请选择引用业务模型',
              trigger: 'change',
            },
          ]"
        >
          <tree-select
            style="width: 100%"
            v-model="formData.referenceModelCode"
            filterable
            :fieldMap="{
              value: 'id',
              label: 'name',
              disabled: 'disabled',
            }"
            :filterNodeMethod="filterNodeMethod"
            :treeData="modelList"
            @change="handleChangeModel"
          />
        </el-form-item>

        <el-form-item
          v-if="formData.type === 'REFERENCE'"
          label="引用字段"
          prop="referenceFieldCode"
          :rules="[
            {
              required: true,
              message: '请选择字段',
              trigger: 'change',
            },
          ]"
        >
          <el-select
            v-model="formData.referenceFieldCode"
            filterable
            style="width: 100%"
          >
            <el-option
              v-for="(item, index) in refFieldList"
              :key="index"
              :value="item.code"
              :label="`${item.name}(${item.code})`"
            />
          </el-select>
        </el-form-item>

        <el-form-item
          v-show="formData.type === 'RELATION'"
          label="关联字段"
          prop="fieldCode"
          :rules="[
            {
              required: formData.type === 'RELATION',
              message: '请选择关联字段',
              trigger: 'change',
            },
          ]"
        >
          <el-select
            v-model="formData.fieldCode"
            filterable
            style="width: 100%"
            @change="handleChangeRelateField"
          >
            <el-option
              v-for="(item, index) in relateFieldList"
              :key="index"
              :value="item.code"
              :label="`${item.name}(${item.code})`"
            />
          </el-select>
        </el-form-item>

        <el-form-item
          v-if="formData.type === 'RELATION'"
          label="运算符"
          prop="operation"
          :rules="[
            {
              required: true,
              message: '请选择运算符',
              trigger: 'change',
            },
          ]"
        >
          <el-select
            v-model="formData.operation"
            filterable
            style="width: 100%"
          >
            <el-option value="eq" label="等于" />
            <el-option value="ne" label="不等于" />
          </el-select>
        </el-form-item>
        <el-form-item
          v-if="formData.type === 'RELATION'"
          label="关联值"
          prop="relationValue"
          :rules="[
            {
              required: true,
              message: '请选择关联值',
              trigger: 'change',
            },
          ]"
        >
          <el-select
            v-model="formData.relationValue"
            filterable
            style="width: 100%"
          >
            <el-option
              v-for="(item, index) in relateValues"
              :key="index"
              :value="item.optionValue"
              :label="item.optionName"
            />
          </el-select>
        </el-form-item>

        <el-form-item
          prop="errorMessage"
          label="异常提示信息"
          :rules="[
            {
              required: true,
              message: '异常提示信息不能为空',
              trigger: 'blur',
            },
          ]"
        >
          <el-input
            type="textarea"
            v-model="formData.errorMessage"
            style="width: 100%"
            placeholder="请输入异常提示信息"
            :maxlength="200"
            show-word-limit
          />
        </el-form-item>

        <el-form-item prop="localism" label="提示信息国际化">
          <GlobalizationConfigWord
            :localism="formData.localism"
            @setLangCode="setLangCode"
          />
        </el-form-item>
      </el-form>
    </div>

    <div slot="footer" class="tr">
      <el-button @click="showVisible = false">取 消</el-button>
      <el-button type="primary" @click="submit">确 定</el-button>
    </div>
  </el-dialog>
</template>

<script>
import GlobalizationConfigWord from "@/components/globalizationConfigWord.vue";
import { getHmmodelfolderListTree } from "@/apis/paas/HmModelFolderController.js";
import { getHmentitymodelList } from "@/apis/paas/HmEntityModelController.js";
import { getHmdictionaryPageList } from "@/apis/paas/HmDictionaryController.js";
import { filterNodeMethod } from "@/utils/treeSelectFormat";
import lodash from "lodash";
import { ACTION_SCOPE_ENUM } from "@/utils/enum";

export default {
  name: "RuleDynamicConfig",
  components: {
    GlobalizationConfigWord,
  },

  props: {
    modelInfo: {
      type: Object,
      default: () => {},
    },
  },
  data() {
    return {
      filterNodeMethod,
      index: 0,
      typeList: {
        UNIQUE: "唯一性规则",
        RELATION: "关联性规则",
        REFERENCE: "引用性规则",
      },
      fieldList: [],
      validateFieldList: [], // 唯一性规则 参与校验字段 过滤系统字段
      uniqueFieldList: [],
      relateFieldList: [], // 关联类型的字段
      referencedFieldList: [], // 引用性规则  被引用的字段  --- id和唯一的字段
      refFieldList:[] ,// 引用性规则 引用字段  ---- 关联引用和关联选择
      modelList: [],
      relateValues: [], // 关联值  --- 字典值
      loading: false,
      showVisible: false,
      formData: {},
      callback: () => {},
      ACTION_SCOPE_ENUM,
    };
  },
  created() {
    // 虚拟模型没有唯一性校验
    if(this.modelInfo.type === 'VIRTUAL'){
       delete this.typeList.UNIQUE
    }
  },
  computed: {
    isNew() {
      return !this.formData.id;
    },
    scopeEnum() {
      if (this.modelInfo?.supportTree) {
        return this.ACTION_SCOPE_ENUM
      } else {
        return { GLOBAL: '全局' }
      }
    }
  },
  methods: {
    setLangCode(props) {
      this.formData.localism = props;
    },
    async addForm(record = {}, index = 0) {
      await this.loadAllFields();
      this.showVisible = true;
      this.index = index;
      this.formData = {
        ...record,
        fieldCodes: [],
        errorMessage: "",
        type: "UNIQUE",
        localism: "",
        actionScope: "GLOBAL"
      };
      if(this.modelInfo.type === 'VIRTUAL'){
        this.formData.type = 'RELATION'
      }
      this.$nextTick(() => {
        this.$refs.form.clearValidate();
      });
    },
    async editForm(record = {}, index = 0) {
      await this.loadAllFields();
      this.formData = {
        localism: "",
        ...record,
      };
      if (this.formData.fieldCodes) {
        this.formData.fieldCodes = record.fieldCodes.match(/\w+/g) || [];
      }
      if (this.formData.referenceModelCode) {
        this.loadModelList("REFERENCE");
      }
      // 字典是:'[11]'数据格式
      if (this.formData.relationValue) {
        let dictType = "";
        this.formData.relationValue = record.relationValue.match(/\w+/g)[0];
        this.fieldList.forEach((item) => {
          if (item.code === record.fieldCode) {
            dictType = JSON.parse(item.config).value;
          }
        });
        this.getHmdictionaryPageList(dictType);
      }
      this.showVisible = true;
      this.index = index;
      this.$nextTick(() => {
        this.$refs.form.clearValidate();
      });
    },

    // 加载模型的的字段
    async loadAllFields(flag = "", id = "") {
      // self 加载模型自身字段
      let modelId = "";
      if (flag === "REFERENCE") {
        // 根据code获取id
        modelId = this.getModelIdByCode(this.formData.referenceModelCode);
      } else {
        modelId = this.modelInfo.id;
      }
      return getHmentitymodelList({
        modelId: modelId,
        activated: true,
      }).then((res) => {
        this.fieldList = res;
        // 唯一性规则过滤系统字段
        this.validateFieldList = res.filter((item) => item.builtIn !== true);
        // 被引用字段
        this.referencedFieldList = res.filter(
          (item) => item.code === "id" || item.uniqueKey
        );
        // 引用字段
        this.refFieldList = res.filter(
            (item) => item.type === "RELATION_REFERENCE" || item.type === "RELATION_SELECT"
        );
        this.relateFieldList = res.filter(
          (item) => item.relationType === "DICTIONARY"
        );
      });
    },
    // 获取所有业务模型
    loadModelList(flag = "") {
      this.modelLoading = true;
      getHmmodelfolderListTree({ modelTypes: "ENTITY" })
        .then((res) => {
          res.forEach((node) => {
            node.type = "folder";
          });
          this.modelList = this.createModelTreeNode(
            res || [],
            this.modelInfo.id
          );
          if (flag === "REFERENCE") {
            this.loadAllFields("REFERENCE");
          }
        })
        .finally(() => {
          this.modelLoading = false;
        });
    },

    handleTypeChange(val) {
      if (val === "REFERENCE") {
        this.loadModelList();
      } else {
        this.loadAllFields()
      }
      this.$set(this.formData, "fieldCode", "");
      this.$set(this.formData, "fieldCodes", []);
      this.$set(this.formData, "operation", "");
      this.$set(this.formData, "referenceFieldCode", "");
      this.$set(this.formData, "referenceModelCode", "");
      this.$set(this.formData, "relationValue", "");
      this.$set(this.formData, "actionScope", "");
      if (val === "UNIQUE") {
        this.$set(this.formData, "actionScope", "GLOBAL");
      }
      this.relateValues = []
      this.fieldList = []
      this.refFieldList = []
      this.$nextTick(() => {
        this.$refs.form.clearValidate();
      });
    },

    handleChangeModel(val) {
      this.loadAllFields("REFERENCE");
      this.$set(this.formData, "referenceFieldCode", "");
    },
   // 切换关联字段
    handleChangeRelateField(val) {
      let dictType = "";
      this.fieldList.forEach((item) => {
        if (item.code === val) {
          dictType = JSON.parse(item.config).value;
        }
      });
      this.getHmdictionaryPageList(dictType);
    },
    getHmdictionaryPageList(dictType) {
      if (!dictType) return;
      getHmdictionaryPageList({ pageSize: 100000, type: dictType }).then(
        (res) => {
          this.relateValues = res.data;
        }
      );
    },
    async submit() {
      try {
        await this.$refs.form.validate();
        const {
          id,
          ruleId,
          type,
          fieldCode,
          fieldCodes,
          operation,
          referenceFieldCode,
          referenceModelCode,
          relationValue,
          errorMessage,
          actionScope,
          localism,
        } = this.formData;
        let params = {};
        if (this.formData.type === "UNIQUE") {
          params = {
            type,
            fieldCodes,
            errorMessage,
            actionScope,
          };
          params.fieldCodes = fieldCodes.join(",");
        } else if (this.formData.type === "RELATION") {
          params = {
            type,
            fieldCode,
            operation,
            relationValue,
            errorMessage,
          };
          // 关联的字典值
          params.relationValue = "[" + relationValue + "]";
        } else if (this.formData.type === "REFERENCE") {
          params = {
            type,
            fieldCode,
            referenceFieldCode,
            referenceModelCode,
            errorMessage,
          };
        }
        params.localism = localism;
        for (const key in params) {
          params[key] =
            typeof params[key] === "string" ? params[key].trim() : params[key];
        }

        const ruleData = {
          index: this.index,
          ruleData: params,
        };
        this.$emit("ok", ruleData);
        this.handleCancel();
      } catch (error) {
        console.log(error);
        return false;
      }
    },
    handleCancel() {
      this.showVisible = false;
      this.$refs.form.resetFields();
      this.formData = {};
      this.fieldList = [];
      this.validateFieldList = [];
      this.relateValues = [];
      this.referencedFieldList = [];
    },
    createModelTreeNode(tree, idDisabled = "") {
      return lodash.cloneDeep(tree).map((node) => {
        node.disabled = node.type === "folder";
        if (node.modelResults) {
          node.id = "folder" + node.id;
          node.children = node.modelResults || [];
          node.children.forEach((item) => {
            item.disabled = item.id == idDisabled;
            item._id = item.id;
            item.id = item.code;
            item.name = `${item.name}（${item.code}）`;
          });
        }
        return node;
      });
    },
    getModelIdByCode(code) {
      let modelId = "";
      this.modelList.forEach((folder) => {
        const children = folder.modelResults || [];
        children.forEach((item) => {
          if (item.code === code) {
            modelId = item._id;
          }
        });
      });
      return modelId;
    },
  },
};
</script>

<style lang="scss" scoped>
.el-form-item.method {
  width: 160px;

  ::v-deep .el-input__inner {
    border-bottom-right-radius: 0;
    border-top-right-radius: 0;
  }
}

.el-form-item.path {
  flex: 1;

  ::v-deep .el-input-group__prepend {
    border-bottom-left-radius: 0;
    border-top-left-radius: 0;
    border-left: none;
  }
}

.request-tabs {
  ::v-deep .el-tabs__header {
    margin-right: 20px;
  }
}
</style>
